<?php

/*
 * wechat robot library
 * @author  terminus
 * @email   terminus.ye@gmail.com
 * @date    2013-03-23
 */

class wechat {

    private $_CI;
    //TOKEN
    private $token;
    //命令超时
    public $cmd_expire_time = 300;
    //命令标识
    public $cmd_sign = '#';
    //帮助消息关键字
    public $help_keyword = 'help_contents';
    //消息模板
    private $textTpl;
    private $newsTpl;
    private $musicTpl;

    public function __construct() {
        $this->_CI = &get_instance();
        $this->_CI->load->config('wechat', TRUE);
        //load TOKEN
        $this->token = $this->_CI->config->item('token', 'wechat');
        //读取超时设置
        $this->cmd_expire_time = $this->_CI->config->item('cmd_expire_time', 'wechat');
        //读取命令标识
        $this->cmd_sign = $this->_CI->config->item('cmd_sign', 'wechat');
        //读取帮助消息关键字
        $this->help_keyword = $this->_CI->config->item('help_keyword', 'wechat');
        //load tpls
        $this->textTpl = $this->_CI->config->item('textTpl', 'wechat');
        $this->newsTpl = $this->_CI->config->item('newsTpl', 'wechat');
        $this->musicTpl = $this->_CI->config->item('musicTpl', 'wechat');
    }

    /*
     * 开发模式验证
     */

    public function valid($data) {
        $echoStr = $data['echostr'];
        $signature = $data['signature'];
        $timestamp = $data['timestamp'];
        $nonce = $data['nonce'];

        if ($this->_checkSignature($signature, $timestamp, $nonce)) {
            echo $echoStr;
            exit;
        }
    }

    /*
     * 验证算法
     */

    private function _checkSignature($signature, $timestamp, $nonce) {
        $tmpArr = array($this->token, $timestamp, $nonce);
        sort($tmpArr);
        $tmpStr = implode($tmpArr);

        if (sha1($tmpStr) == $signature) {
            return TRUE;
        }
        return FALSE;
    }

    /*
     * 解析XML
     */

    public function resloveMsg($serverMsg) {
        $postObj = simplexml_load_string($serverMsg, 'SimpleXMLElement', LIBXML_NOCDATA);

        $this->_CI->load->model('msgtype_model', 'msgtype');

        $msgtype = $this->_CI->msgtype->getMsgtype(strval($postObj->MsgType), 0);

        $msgArr = array(
            'user_opn_id' => strval($postObj->FromUserName),
            'platform_opn_id' => strval($postObj->ToUserName),
            'msgtype' => strval($postObj->MsgType),
            'msgtype_id' => ($msgtype ? $msgtype->id : 0),
            'content' => json_encode($postObj),
            'post_time' => intval($postObj->CreateTime),
            'wx_msg_id' => strval($postObj->MsgId)
        );

        //save to msgbox
        $this->_CI->load->model('msgbox_model', 'msgbox');

        $mid = $this->_CI->msgbox->addMsg($msgArr['user_opn_id'], $msgArr['platform_opn_id'], $msgArr['msgtype_id'], $msgArr['content'], $msgArr['post_time'], $msgArr['wx_msg_id']);

        if ($mid > 0) {
            $msg = new stdClass();
            $msg->mid = $mid;
            $msg->msgArr = $msgArr;
            return $msg;
        }
        return 'err_can_not_save_msg_to_db';
    }

    /*
     * 发送信息
     */

    public function sendMsg($msgData) {
        if (!is_object($msgData)) {
            exit('err_incorrect_msg_format');
        }

        $user_opn_id = $msgData->msgArr['user_opn_id'];
        $platform_opn_id = $msgData->msgArr['platform_opn_id'];
        $reply_msg = $msgData->reply_msg;

        switch ($reply_msg->reply_msgtype) {
            case 'text':
                /*
                 * options:
                 * xml,
                 * sender,
                 * consignee,
                 * send time,
                 * message type[text],
                 * content
                 */
                $resultStr = sprintf($this->textTpl, $user_opn_id, $platform_opn_id, time(), 'text', $reply_msg->content);
                break;
            case 'news':
                /*
                 * options:
                 * xml,
                 * sender,
                 * consignee,
                 * send time,
                 * message type[news],
                 * news title,
                 * news description,
                 * news picture,
                 * news url
                 */
                $resultStr = sprintf($this->newsTpl, $user_opn_id, $platform_opn_id, time(), 'news', $reply_msg->title, $reply_msg->description, $reply_msg->pic_url, $reply_msg->link_url);
                break;
            case 'music':
                /*
                 * options:
                 * xml,
                 * sender,
                 * consignee,
                 * send time,
                 * message type[music],
                 * music title,
                 * music description,
                 * music url,
                 * HQ music url[wifi mode will play this one]
                 */
                $resultStr = sprintf($this->musicTpl, $user_opn_id, $platform_opn_id, time(), 'music', $reply_msg->title, $reply_msg->description, $reply_msg->music_url, $reply_msg->hqmusic_url);
                break;
            default :
                //wrong type,exit
                $resultStr = 'err_incorrect_msgtype_' . $reply_msg->msgType;
                exit($resultStr);
        }
        //delete space char
        $resultXML = preg_replace('/[\r|\t]/', '', $resultStr);
        //save reply msg to db
        $this->_CI->load->model('msgbox_model', 'msgbox');
        $this->_CI->msgbox->setMsg($msgData->mid, (empty($reply_msg->reply_msgtype_id) ? 0 : $reply_msg->reply_msgtype_id), json_encode($reply_msg));
        //output msg
        echo $resultXML;
    }

}